/////////////////////////////////////////////////////////////////////////////
/*/	

/*/
/////////////////////////////////////////////////////////////////////////////
#include "BaseUnit.h"
#include "SGD_Math.h"
#include "MessageSystem.h"
#include "Bullet.h"
#include "LevelManager.h"
#include "CSGD_TextureManager.h"
#include "CSGD_XAudio2.h"
#include "EntityManager.h"
#include "LevelManager.h"
#include "AnimInfo.h"
#include "Game.h"

/////////////////////////////////////////////////////////////////////////////
// Function : Default constructor
// Notes	: Assigns basic values to variables
/////////////////////////////////////////////////////////////////////////////
CBaseUnit::CBaseUnit(){
	m_eType = BASEUNIT;
	m_fHealth			= 100;
	m_fAttackCooldown	= 1;
	m_fSpecAttCooldown	= 15;
	m_fAttackWait		= 1;
	m_fSAttackWait		= 20;
	m_fBaseDamage		= 20;
	m_fSpecialDamage	= 25;
	m_pTarget			= nullptr;
	SetDeathID(CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("resource\\Sounds\\YouScrewedUp.wav")));
	SetShotID(CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("resource\\Sounds\\InfantryShot.wav")));

}
/////////////////////////////////////////////////////////////////////////////
// Function		: Constructor
// Parameters	: fHealth - The health the unit will start with
//					fAttCool - The special attack cooldown time
//					fBaseDmg - The unit's basic attack strength
//					fSpDmg - The unit's special attack strength
// Notes		: Assigns provided values to variables
/////////////////////////////////////////////////////////////////////////////
CBaseUnit::CBaseUnit(float fHealth, float fAttCool, float fSAttCool, float fBaseDmg, float fSpDmg){
	m_fHealth			= fHealth;
	m_fAttackCooldown	= fAttCool;
	m_fSpecAttCooldown	= fSAttCool;
	m_fBaseDamage		= fBaseDmg;
	m_fSpecialDamage	= fSpDmg;
	SetDeathID(CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("resource\\Sounds\\YouScrewedUp.wav")));
	SetShotID(CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("resource\\Sounds\\InfantryShot.wav")));
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Destructor
// Notes		: Cleans up any dynamically allocated memory
/////////////////////////////////////////////////////////////////////////////
CBaseUnit::~CBaseUnit(){}
/////////////////////////////////////////////////////////////////////////////
// Function		: Update
// Parameters	: dT - Time elapsed since last update
// Notes		: Updates the unit's variables based on elapsed time
/////////////////////////////////////////////////////////////////////////////
void CBaseUnit::Update(float dT){
	//update cooldowns	
	SetAttackCool(GetAttackCool() - dT);
	SetSpecAttCool(GetSpecAttCool() - dT);
	//Check for a target

	CBaseUnit* previousunit = nullptr;

	for (unsigned int i = 0; i < CEntityManager::GetInstance()->m_BaseUnits.size(); i++)
	{
		if(i != 0)
		{
			if(GetPosX() == CEntityManager::GetInstance()->m_BaseUnits[i]->GetPosX())
			{
				int backcount = i-1;
				for (;backcount != -1; backcount--)
				{
					if(GetTeam() == CEntityManager::GetInstance()->m_BaseUnits[backcount]->GetTeam()&& GetPath() ==  CEntityManager::GetInstance()->m_BaseUnits[backcount]->GetPath())
					{
						previousunit = (CBaseUnit*)(CEntityManager::GetInstance()->m_BaseUnits[backcount]);
						break;
					}
				}
				break;
			}
		}
	}

	if(m_pTarget == nullptr){
		//Walk to the next waypoint
		if(previousunit == nullptr || (GetTeam() == 1 && GetPosX() < previousunit->GetPosX()-32) || (GetTeam() == 2 && GetPosX() > previousunit->GetPosX()+32))
		{
			tVector2D toWaypoint;
			toWaypoint.fX = m_cCurWaypoint->GetPos().m_nPosX - GetPosX();
			toWaypoint.fY = m_cCurWaypoint->GetPos().m_nPosY - GetPosY();
			toWaypoint = Vector2DNormalize( toWaypoint );

			toWaypoint.fX = toWaypoint.fX * GetVelX() * dT;
			toWaypoint.fY = toWaypoint.fY * GetVelY() * dT;

			SetPosX( GetPosX() + toWaypoint.fX );
			SetPosY( GetPosY() + toWaypoint.fY );
		}	
	}
	else{
		//Check if special attack has cooled down
		if(GetSpecAttCool() <= 0.0f){
			//Perform special attack
			//Send message through system
		}
		//otherwise check if it can attack normally
		if(GetAttackCool() <= 0.0f)
		{
			//Perform normal attack
			//Send message through system
			CBullet* bullet = new CBullet( this );
			if(m_eType != ROCKET)
			{
				CSGD_XAudio2::GetInstance()->SFXPlaySound(GetShotID());
				bullet->SetImage( CSGD_TextureManager::GetInstance()->LoadTexture( _T("resource/Images/Bullet.png") ) );
				bullet->SetWidth(8);
				bullet->SetHeight(8);
			}else
			{
				bullet->SetWidth(21);
				bullet->SetHeight(9);
				bullet->SetImage( CSGD_TextureManager::GetInstance()->LoadTexture( _T("resource/Images/Rocket.png"),D3DCOLOR_ARGB(255,255,255,255) ) );
			}

			bullet->SetDeathY(600);


			bullet->SetPosX( GetPosX() + GetWidth()/2 );
			bullet->SetPosY( GetPosX() + GetHeight()/2 );

			bullet->SetPath(GetPath());

			if( m_pTarget->GetType() == BOSS )
				bullet->SetPath( 0 );


			switch (GetType())
			{
			case SHOOT:
				if(GetTeam() == 1)
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP1(0) ));
				else
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP2(0) ));
				break;

			case SHIELD:
				if(GetTeam() == 1)
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP1(1) ));
				else
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP2(1) ));
				break;

			case ROCKET:
				if(GetTeam() == 1)
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP1(2) ));
				else
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP2(2) ));
				break;

			case MECH:
				if(GetTeam() == 1)
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP1(3) ));
				else
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP2(3) ));
				break;

			case HELI:
				if(GetTeam() == 1)
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP1(4) ));
				else
					bullet->SetDamage((int)( (rand() % (int)GetBaseDmg()) + 3 * CLevelManager::GetInstance()->GetCurrLevel()->GetLevelP2(4) ));
				break;

			default:
				break;
			}

			tVector2D vTarget = { (m_pTarget->GetPosX() + m_pTarget->GetWidth()/2) - bullet->GetPosX(), 
				(m_pTarget->GetPosY() + m_pTarget->GetHeight()/2) - bullet->GetPosY()};
			vTarget = Vector2DNormalize(vTarget);

			SetVelX( vTarget.fX * 100 );
			SetVelY( vTarget.fY * 100 );

			CEntityManager::GetInstance()->AddEntity(bullet);
			SetAttackCool(1.0f);
		}
		//otherwise do nothing
	}

	SetTarget(nullptr);
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Render
// Notes		: Renders the unit to the screen
/////////////////////////////////////////////////////////////////////////////
void CBaseUnit::Render(){
	CMovingObject::Render();
}

std::vector<CBaseUnit*> CBaseUnit::GetEnemiesInRange()
{
	std::vector<CBaseUnit*> fullList;
	std::vector<CBaseUnit*> returnList;

	if(this->GetTeam() == 1)
	{
		if( CLevelManager::GetInstance()->GetCurrLevel()->m_bBossLevel == false )
		{
			if(this->GetPath() == 1)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath1Units();
			else if(this->GetPath() == 2)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath2Units();
			else if(this->GetPath() == 3)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath3Units();
		}
		else
		{
			for( unsigned int i = 0; i < CEntityManager::GetInstance()->m_BaseUnits.size(); ++i )
			{
				if( CEntityManager::GetInstance()->m_BaseUnits[i]->GetTeam() != 1 )
				{
					CBaseUnit* unit = dynamic_cast<CBaseUnit*>(CEntityManager::GetInstance()->m_BaseUnits[i]);
					if( unit )
					{
						fullList.push_back(unit);
					}
				}
			}
		}
	}
	else if(this->GetTeam() == 2)
	{
		if(this->GetPath() == 1)
			fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath1Units();
		else if(this->GetPath() == 2)
			fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath2Units();
		else if(this->GetPath() == 3)
			fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath3Units();
	}

	for (unsigned int i = 0; i < fullList.size(); i++)
	{
#if _DEBUG
		int test = DistanceBetween(fullList[i]->GetPos(),this->GetPos());
#endif
		if(DistanceBetween(fullList[i]->GetPos(),this->GetPos()) <= GetRange())
			returnList.push_back(fullList[i]);
		else if(fullList[i]->GetType() == BOSS && fullList[i]->GetPosX() - GetPosX() <= GetRange())
			returnList.push_back(fullList[i]);
	}

	return returnList;
}

CDefenseStruct* CBaseUnit::GetClosestGate()
{
	std::vector<CDefenseStruct*> list;
	std::vector<CDefenseStruct*> generators;

	switch(this->GetTeam())
	{
	case 1:
		if(CLevelManager::GetInstance()->GetCurrLevel()->m_bBossLevel == false)
		{
			if(this->GetPath() == 1)
				list = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath1Gates();
			else if(this->GetPath() == 2)													 
				list = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath2Gates();
			else if(this->GetPath() == 3)													 
				list = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath3Gates();
			// add base and shields
			generators = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetShield()->GetGenerators();
			for(unsigned int i = 0; i < generators.size(); ++i)
				list.push_back( generators[i] );
			list.push_back( CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase());
		}
		break;
	case 2:
		if(this->GetPath() == 1)
			list = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath1Gates();
		else if(this->GetPath() == 2)											
			list = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath2Gates();
		else if(this->GetPath() == 3)												
			list = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath3Gates();
		// add base and shields
		generators = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetShield()->GetGenerators();
		for(unsigned int i = 0; i < generators.size(); ++i)
			list.push_back( generators[i] );
		list.push_back( CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase());
		break;
	}

	if( list.size() == 0 )
		return nullptr;

	CDefenseStruct* closest = list[0];

	for(unsigned int i = 0; i < list.size(); i++)
	{
		int j = DistanceBetween(list[i]->GetPos(),this->GetPos());
		int k = DistanceBetween(closest->GetPos(),this->GetPos());


		if(j < k)
			closest = list[i];
	}
	return closest;
}